﻿using System;
using System.IO;
using WeifenLuo.WinFormsUI.Docking;
using System.Windows.Forms;
using System.Xml;
using System.Threading;
using Spider.Lib;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using Models;
using Services;
using System.Linq;
using log4net;
using System.Drawing;

namespace Spider.Forms
{
    public partial class StandSpider : DockContent
    {
        string appDir = AppDomain.CurrentDomain.BaseDirectory.Replace("\\bin\\Debug", "");

        #region 事件
        public StandSpider()
        {
            InitializeComponent();
        }

        private void StandSpider_Load(object sender, EventArgs e)
        {
            //绑定cbxTask
            BindCombox(appDir + "Tasks", cbxTasks);
            //cbxTasks.Enabled = false;
            //绑定cbxRule
            BindCombox(appDir + "Rules", cbxRules);

            //根据配置,绑定控件的值
            BindControls("TaskConfig.xml");

            //handleWatermark(@"D:\Project\CMS\WebApp\_upload\img\7.jpg");
        }

        private void cbxTasks_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cbxTasks.SelectedItem != null)
            {
                BindControls(cbxTasks.SelectedItem.ToString());
            }

        }
        private void cbxRules_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cbxRules.SelectedItem != null)
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(appDir + "Rules\\" + cbxRules.SelectedItem.ToString());

                Text = doc.SelectSingleNode("RuleConfigInfo/SiteName/Pattern").InnerText + " -  采集";
                txtListUrl.Text = doc.SelectSingleNode("RuleConfigInfo/ListUrl/Pattern").InnerText;
            }
        }

        #endregion

        #region 私有方法
        void BindCombox(string xmlPath, ComboBox comboBox)
        {
            DirectoryInfo info = new DirectoryInfo(xmlPath);
            var files = info.GetFiles("*.xml");
            comboBox.Items.Clear();
            foreach (var file in files)
            {
                comboBox.Items.Add(file.Name);
            }
        }

        void BindControls(string taskXml)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(appDir + "Tasks\\" + taskXml);
            try
            {
                XmlNodeList nodelist = doc.SelectSingleNode("TaskConfigInfo").ChildNodes;
                foreach (XmlNode node in nodelist)
                {
                    var controls = Controls.Find(node.Name, true);
                    if (controls.Length > 0)
                    {
                        if (controls[0] is ComboBox)
                        {
                            ComboBox _combox = controls[0] as ComboBox;
                            _combox.SelectedItem = node.InnerText;
                        }
                        else if (controls[0] is RadioButton)
                        {
                            bool _is = false;
                            bool.TryParse(node.InnerText, out _is);
                            RadioButton _btn = controls[0] as RadioButton;
                            _btn.Checked = _is;
                        }
                        else if (controls[0] is CheckBox)
                        {
                            bool _is = false;
                            bool.TryParse(node.InnerText, out _is);
                            CheckBox _btn = controls[0] as CheckBox;
                            _btn.Checked = _is;
                        }
                        else if (controls[0] is TextBoxBase)
                        {
                            var _txt = controls[0] as TextBoxBase;
                            _txt.Text = node.InnerText;
                        }
                        else if (controls[0] is UpDownBase)
                        {
                            var _txt = controls[0] as UpDownBase;
                            _txt.Text = node.InnerText;
                        }
                    }
                }
                cbxRules_SelectedIndexChanged(null, null);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        string getRuleConfigPattern(EnumRule rule)
        {
            string retValue = string.Empty;
            var node = ruleConfig.SelectSingleNode(EnumConfigType.RuleConfigInfo + "/" + rule + "/" + EnumRuleItem.Pattern);
            if (node != null)
                retValue = node.InnerText.ToString();

            return retValue;
        }
        string getRuleConfigFilter(EnumRule rule)
        {
            string retValue = string.Empty;
            var node = ruleConfig.SelectSingleNode(EnumConfigType.RuleConfigInfo + "/" + rule + "/" + EnumRuleItem.FilterPattern);
            if (node != null)
                retValue = node.InnerText.Trim();

            return retValue;
        }

        //string getBaseConfigInnerText(EnumRule rule, EnumRuleItem item)
        //{
        //    return baseConfig.SelectSingleNode("BaseConfigInfo/" + rule + "/" + item).InnerText.Trim();
        //}

        string getHtmlContentByUrl(string url)
        {
            string _htmlContent = string.Empty;
            try
            {
                int timeout = 20000;
                if (ckbProxy.Checked)
                {
                    string proxyHost = txtProxyHost.Text.Trim();
                    int proxyPort = int.Parse(txtProxyPort.Text.Trim());
                    string proxyUserName = txtProxyUserName.Text.Trim();
                    string proxyPassword = txtProxyPassword.Text.Trim();

                    _htmlContent = MyHttpClient.Get(url, timeout, proxyHost, proxyPort, proxyUserName, proxyPassword);
                }
                else
                {
                    _htmlContent = MyHttpClient.Get(url, timeout);
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
            }

            return _htmlContent;
        }

        List<string> GetMatchs(string input, string pattern)
        {
            List<string> arry = new List<string>();
            MatchCollection matchs = Regex.Matches(input, pattern);
            foreach (Match item in matchs)
            {
                arry.Add(item.Groups[1].Value);
            }
            return arry;
        }

        string GetMatch(string input, string pattern)
        {
            string match = string.Empty;
            MatchCollection matchs = Regex.Matches(input, pattern);
            foreach (Match item in matchs)
            {
                match = item.Groups[1].Value;
            }
            return match;
        }

        string GetFilter(string input, string filterPattern)
        {
            string[] filterArray = filterPattern.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            foreach (var filter in filterArray)
            {
                if (!filter.Contains("|")) continue;
                var replaceArray = filter.Split('|');
                input = Regex.Replace(input, replaceArray[0], replaceArray[1]);
            }
            return input;
        }

        string GetBaseConfigFilter(string input)
        {
            string[] filterArray = StringFactory.Filter.Split('|');
            foreach (var filter in filterArray)
            {
                if (filter.Trim() == "") continue;
                input = Regex.Replace(input, filter, "***");
            }
            return input;
        }

        string GetTag(string tag)
        {
            string[] taglines = StringFactory.Tag.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            foreach (var tagline in taglines)
            {
                if (!tagline.Contains("=")) continue;
                string[] tagSplit = tagline.Split("=".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                if (tagSplit[1].Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).Contains(tag))
                {
                    tag = tagSplit[0];
                    break;
                }
            }

            return tag;
        }

        string GetCategory(string category)
        {
            string[] categorylines = StringFactory.Category.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            foreach (var categoryline in categorylines)
            {
                if (!categoryline.Contains("=")) continue;
                string[] categorySplit = categoryline.Split("=".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                if (categorySplit[1].Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).Contains(category))
                {
                    category = categorySplit[0];
                    break;
                }
            }

            return category;
        }
        #endregion

        Thread thread1 = null;
        System.Threading.Timer time = null;
        XmlDocument ruleConfig = null;
        XmlDocument baseConfig = null;
        private void btnStart_Click(object sender, EventArgs e)
        {
            if (cbxRules.SelectedItem == null)
            {
                MessageBox.Show("选择规则");
                return;
            }

            ruleConfig = new XmlDocument();
            baseConfig = new XmlDocument();
            ruleConfig.Load(appDir + "Rules\\" + cbxRules.SelectedItem.ToString());
            baseConfig.Load(appDir + "BaseConfig.xml");

            try
            {

                if (ckbLoop.Checked)
                {
                    time = new System.Threading.Timer(new TimerCallback(btnDo_Work), null, 0, int.Parse((numMinutes.Value * 60 * 1000).ToString()));
                }
                else
                {
                    thread1 = new Thread(btnDo_Work);
                    thread1.Start();
                }
                btnStart.Enabled = false;
                btnStop.Enabled = true;
                tabControl1.SelectedTab = tabPage3;
            }
            catch (Exception ex)
            {
                // log
                LogHelper.Error(ex);
                btnStop_Click(null, null);
            }


        }


        private void btnStop_Click(object sender, EventArgs e)
        {
            try
            {
                if (time != null)
                    time.Dispose();

                if (thread1 != null)
                    thread1.Abort();
            }
            catch (Exception ex)
            {
                // log
                LogHelper.Error(ex);
            }
            finally
            {
                StringFactory.ThreadState = "Stop";
                btnStart.Enabled = true;
                btnStop.Enabled = false;
            }
        }

        private void btnSolution_Click(object sender, EventArgs e)
        {
            //ILog log = LogManager.GetLogger("log4net");
            //log.Error("abc");
            // LogHelper.Error("ddd");
            // tabControl1.SelectedTab = tabPage3;
            // tabControl1.SelectTab(2);
        }

        void btnDo_Work(object obj)
        {
            if (StringFactory.ThreadState == "Start")
                return;
            StringFactory.ThreadState = "Start";

            List<string> urlAarry = new List<string>();
            //获得配置的 ListUrl
            //string _listUrl = getRuleConfigPattern(EnumRule.ListUrl);
            string _listUrl = txtListUrl.Text.Trim();
            if (rbListUrl.Checked)
            {

                string _htmlContent = getHtmlContentByUrl(_listUrl);

                //获得配置的 正则
                string _getUrlKey = getRuleConfigPattern(EnumRule.GetUrlKey);
                var urlList = GetMatchs(_htmlContent, _getUrlKey);

                //获得 url关键词
                string _url = getRuleConfigPattern(EnumRule.Url);
                foreach (string url in urlList)
                {
                    urlAarry.Add(_url.Replace("{UrlKey}", url));
                }
            }
            else if (rbSequenceNum.Checked)
            {
                for (int i = int.Parse(numStart.Value.ToString()); i < int.Parse(numEnd.Value.ToString()); i++)
                {
                    urlAarry.Add(_listUrl + i + txtHouZhui.Text.Trim());
                }
            }
            else if (rbNumbers.Checked)
            {
                var Ids = txtNumbers.Text.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                foreach (var id in Ids)
                {
                    urlAarry.Add(_listUrl + id.Trim() + txtHouZhui.Text.Trim());
                }
            }

            if (urlAarry.Count > 0)
                GetHtmlContents(urlAarry);


            StringFactory.ThreadState = "Stop";
            UpdateProgress(100);
            UpdateLabel("结束!!");

            if (btnStart.InvokeRequired)
            {
                Action<bool> actionDeletegate = (x) =>
                {
                    btnStop.Enabled = false;
                    btnStart.Enabled = true;
                };
                btnStart.Invoke(actionDeletegate, false);
            }
        }


        //这里获得都是[详细页]地址
        ContentsServices contentServs = new ContentsServices();
        TagServices tagServs = new TagServices();
        CategoryServices categoryServs = new CategoryServices();
        RelevanceServices relevServs = new RelevanceServices();
        void GetHtmlContents(List<string> urlAarry)
        {
            string framePath = StringFactory.WebSiteDir + "\\Admins\\Templates\\frame.html";
            string viewHtml = IOHelper.Read(framePath);

            int prior = 100 / urlAarry.Count;
            int i = 1;
            foreach (string url in urlAarry)
            {
                UpdateProgress(i * prior);
                i++;

                UpdateLabel("获得数据:" + url);
                string detailHtml = getHtmlContentByUrl(url);

                UpdateLabel("匹配名称:" + url);
                string name = GetMatch(detailHtml, getRuleConfigPattern(EnumRule.Name));
                name = GetFilter(name, getRuleConfigFilter(EnumRule.Name));
                if (string.IsNullOrEmpty(name))
                    continue;

                UpdateLabel("匹配状态:" + url);
                string state = GetMatch(detailHtml, getRuleConfigPattern(EnumRule.State));
                state = GetFilter(state, getRuleConfigFilter(EnumRule.State));

                UpdateName("名称:" + name);
                UpdateState("状态:" + state);
                UpdateLabel("匹配图片:" + url);

                string img = GetMatch(detailHtml, getRuleConfigPattern(EnumRule.Img));
                img = GetFilter(img, getRuleConfigFilter(EnumRule.Img));

                #region 匹配标签,过滤标签,并在配置中找到对应的标签
                UpdateLabel("匹配标签:" + url);

                List<string> tags = GetMatchs(detailHtml, getRuleConfigPattern(EnumRule.Tag));
                List<string> FindTags = new List<string>();
                foreach (var tag in tags)
                {
                    var _tag = GetFilter(tag, getRuleConfigFilter(EnumRule.Tag));
                    if (!string.IsNullOrEmpty(_tag))
                        FindTags.Add(GetTag(_tag));
                }


                #endregion

                #region 匹配类别,过滤类别,并在配置中找到对应的类别
                UpdateLabel("匹配类别:" + url);

                List<string> categorys = GetMatchs(detailHtml, getRuleConfigPattern(EnumRule.Category));
                List<string> FindCategory = new List<string>();
                foreach (var category in categorys)
                {
                    var _category = GetFilter(category, getRuleConfigFilter(EnumRule.Category));
                    if (!string.IsNullOrEmpty(_category))
                        FindCategory.Add(GetCategory(_category));
                }

                #endregion


                UpdateLabel("匹配内容:" + url);

                string contents = GetMatch(detailHtml, getRuleConfigPattern(EnumRule.Contents));
                contents = GetFilter(contents, getRuleConfigFilter(EnumRule.Contents));

                UpdateLabel("匹配简介:" + url);
                string intro = GetMatch(detailHtml, getRuleConfigPattern(EnumRule.Intro));
                intro = GetFilter(intro, getRuleConfigFilter(EnumRule.Intro));
                //过滤敏感词
                contents = GetBaseConfigFilter(contents);

                if (!contentServs.Exists(t => t.Name == name && t.State == state))
                {
                    #region 处理内容

                    UpdateLabel("处理内容:" + url);

                    Contents _contentsAdd = new Contents();
                    _contentsAdd.Id = Guid.NewGuid();
                    _contentsAdd.Name = name;
                    _contentsAdd.State = state;
                    _contentsAdd.UpdateTime = DateTime.Now;
                    _contentsAdd.SourceUrl = url;
                    _contentsAdd.Intro = intro;
                    contentServs.Save(_contentsAdd);
                    _contentsAdd = contentServs.GetByID(_contentsAdd.Id);

                    //保存图片地址
                    if (ckbImgLocal.Checked)
                    {
                        UpdateLabel("下载图片:" + img);
                        string imgLocalPath = "\\_upload\\img\\" + _contentsAdd.Seed / 1000 + "\\" + _contentsAdd.Seed + ".jpg";

                        try
                        {
                            string localImg = StringFactory.WebSiteDir + imgLocalPath;
                            MyHttpClient.HttpDownloadFile(img, localImg);

                            //去掉图片的logo
                            handleWatermark(localImg);
                        }
                        catch (Exception ex)
                        {
                            LogHelper.Error(ex.Message);
                        }

                        _contentsAdd.ImgUrl = imgLocalPath;
                    }
                    else
                    {
                        _contentsAdd.ImgUrl = img;
                    }

                    contentServs.Save(_contentsAdd);

                    //保存内容到本地
                    UpdateLabel("保存内容");
                    string contentsLocalPath = "\\_upload\\contents\\" + _contentsAdd.Seed / 1000 + "\\" + _contentsAdd.Seed + ".txt";
                    IOHelper.Write(contents, StringFactory.WebSiteDir + contentsLocalPath);

                    #endregion

                    #region 处理tag
                    UpdateLabel("处理标签");
                    foreach (var item_tag in FindTags)
                    {
                        Guid tagid = Guid.Empty;
                        if (tagServs.Exists(item_tag))
                        {
                            tagid = tagServs.GetByName(item_tag).TagId;
                        }
                        else
                        {
                            tagid = Guid.NewGuid();
                            tagServs.Save(new Tag() { TagId = tagid, TagName = item_tag, TagUrl = ChineseConverter.GetFirstPinyin(item_tag).ToLower() });
                        }
                        relevServs.Save(new Relevance() { FirstId = _contentsAdd.Id, SecondId = tagid, TableName = "contents_tag" });
                    }

                    #endregion

                    #region 处理Category
                    UpdateLabel("处理类别");

                    foreach (var item_category in FindCategory)
                    {
                        Guid categoryId = Guid.Empty;
                        if (categoryServs.Exists(item_category))
                        {
                            categoryId = categoryServs.GetByName(item_category).CategoryId;
                        }
                        else
                        {
                            categoryId = Guid.NewGuid();
                            categoryServs.Save(new Category() { CategoryId = categoryId, CategoryName = item_category, CategoryUrl = ChineseConverter.GetFirstPinyin(item_category).ToLower() });
                        }

                        relevServs.Save(new Relevance() { FirstId = _contentsAdd.Id, SecondId = categoryId, TableName = "contents_category" });
                    }
                    #endregion

                    #region 生成静态页
                    UpdateLabel("生成静态页");
                    new CreateStaticHtml().CreateHtml(_contentsAdd, contents, viewHtml);

                    #endregion

                }
            }

        }
        #region 通知界面展示

        private void UpdateLabel(object str)
        {
            if (lblCurrentAction.InvokeRequired)
            {
                Action<string> actionDelegate = (x) =>
                {
                    this.lblCurrentAction.Text = x.ToString();
                };
                lblCurrentAction.Invoke(actionDelegate, str);

            }
            else
            {
                lblCurrentAction.Text = str.ToString();
            }
        }
        private void UpdateName(object str)
        {
            if (lblName.InvokeRequired)
            {
                Action<string> actionDelegate = (x) =>
                {
                    this.lblName.Text = x.ToString();
                };
                lblName.Invoke(actionDelegate, str);

            }
            else
            {
                lblName.Text = str.ToString();
            }
        }
        private void UpdateState(object str)
        {
            if (lblState.InvokeRequired)
            {
                Action<string> actionDelegate = (x) =>
                {
                    this.lblState.Text = x.ToString();
                };
                lblState.Invoke(actionDelegate, str);

            }
            else
            {
                lblState.Text = str.ToString();
            }
        }
        private void UpdateProgress(int str)
        {
            if (progressBar1.InvokeRequired)
            {
                Action<int> actionDelegate = (x) =>
                {
                    this.progressBar1.Value = str;
                };
                progressBar1.Invoke(actionDelegate, str);
            }
            else
            {
                progressBar1.Value = str;
            }
        }

        #endregion

        #region 处理图片水印
        private void handleWatermark(string ImgFile)
        {
            if (!StringFactory.EnableMark)
                return;

            FileStream fs = new FileStream(ImgFile, FileMode.Open);
            BinaryReader br = new BinaryReader(fs);
            byte[] bytes = br.ReadBytes((int)fs.Length);
            br.Close();
            fs.Close();
            MemoryStream ms = new MemoryStream(bytes);
            Image imgPhoto = Image.FromStream(ms);
            //System.Drawing.Image imgPhoto = System.Drawing.Image.FromFile(ImgFile);
            Graphics g1 = Graphics.FromImage(imgPhoto);
            //SolidBrush b = new SolidBrush(Color.White);
            //int imgPhotoWidth = imgPhoto.Width;
            //int imgPhotoHeight = imgPhoto.Height;
            //g1.DrawString("www.dianying.com", new Font("宋体", 15), b, imgPhotoWidth/2, imgPhotoHeight-20);
            Image mark = Image.FromFile(StringFactory.WaterMarkJpg);

            g1.DrawImage(mark, 0, imgPhoto.Height - StringFactory.ImgHeigh);
            g1.Save();

            imgPhoto.Save(ImgFile);
        }

        #endregion
    }
}
